package com.qingxin.sys.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.qingxin.sys.dao.Updater;
import com.qingxin.sys.entity.LoginUser;
import com.qingxin.sys.entity.SysPermission;
import com.qingxin.sys.mvc.Pager;
import com.qingxin.sys.mvc.SysError;
import com.qingxin.sys.support.SystemCfg;
import com.qingxin.sys.utils.BeanUtil;
import com.qingxin.sys.utils.StringUtils;
import com.qingxin.ui.bean.TreeNode;
import com.qingxin.ui.bean.UIModule;

/**
 * 权限表
 * @author Administrator
 *
 */
@Service
public class SysPermissionService extends BaseService<SysPermission, String> {

	/**
	 * 获取模块列表
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<UIModule> getUIModules(){
		List<UIModule> modules = listByHql("select new com.qingxin.ui.bean.UIModule(" +
				"perid,per_code,per_name,remark,url,icon,type)" +
				" from SysPermission where pid='0' order by per_index asc");
		if(modules == null){
			return new ArrayList<>();
		}
		return modules;
	}
	
	
	
	@SuppressWarnings("unchecked")
	public List<SysPermission> getMenudata(){
		List<SysPermission> list = listByHql("from SysPermission where type='1' order by per_index asc");
		return list;
	}
	
	
	/**
	 * 获取指定用户的权限编号集合
	 * @param userid
	 * @return
	 */
	@Cacheable(value="userRightsCache", key="'GetUserPermissionCodes_' + #userid")
	@SuppressWarnings("unchecked")
	public Set<String> getUserPermissionCodes(String userid){
		Set<String> set = new HashSet<String>();
		String hql = "select distinct v.per_code from SysUserRightsView v where v.userid=?";
		List<String> list = listByHql(hql, userid);
		if(list != null){
			for(String code : list){
				set.add(code.toUpperCase());
			}
		}
		return set;
	}
	
	
	
	/**
	 * 根据URL获取权限项
	 * @param url
	 * @return
	 */
	@Cacheable(value="userRightsCache", key="'GetPermissionByUrl_' + #url")
	public SysPermission getPermissionByUrl(String url) {
		SysPermission permission = (SysPermission) getByHql("select new com.qingxin.sys.entity.SysPermission(per_code, url)" +
				" from SysPermission where url=?", url);
		return permission;
	}
	
	
	/**
	 * 根据URL获取权限项
	 * @param url
	 * @return
	 */
	@Cacheable(value="userRightsCache", key="'GetPermissionsByUrl_' + #url")
	@SuppressWarnings("unchecked")
	public List<SysPermission> getPermissionsByUrl(String url) {
		List<SysPermission> list = listByHql("select new com.qingxin.sys.entity.SysPermission(per_code, url)" +
				" from SysPermission where url like '"+url+"%'");
		return list;
	}
	
	
	/**
	 * 删除指定用户权限缓存
	 * @param userid
	 */
	public void evictUserRightsCache(String userid){
		evictCache("userRightsCache", "GetUserPermissionCodes_"+userid);
	}
	
	
	/**
	 * 刷新用户权限缓存
	 * @param request
	 * @return
	 */
	@CacheEvict(value="userRightsCache", allEntries = true)
	public Object refreshUserRightsCache(HttpServletRequest request){
		evictCache("userRightsCache", null);
		return null;
	}
	
	
	/**
	 * 获取权限菜单树数据
	 * @param pid
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<TreeNode> getMenuData(String pid){
		List<TreeNode> list = new ArrayList<TreeNode>();
		List<SysPermission> perList = listByHql("from SysPermission where pid=? order by per_index asc", pid);
		if(perList == null){
			return list;
		}
		for(SysPermission perm : perList){
			list.add(new TreeNode(perm.getPerid(), perm.getPer_name(), "PERM", "perid", true));
		}
		return list;
	}
	
	
	/**
	 * 获取指定PID下的数据
	 * @param pid
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Pager listData(String pid){
		List<SysPermission> list = listByHql("from SysPermission where pid=? order by per_index asc", pid);
		if(list == null){
			return new Pager();
		}
		return new Pager(list, list.size());
	}
	
	
	/**
	 * 添加权限项
	 * 
	 * @param permission
	 * @return
	 */
	@CacheEvict(value="userRightsCache", allEntries = true)
	public Object add(SysPermission permission){
		evictCache("userRightsCache", null);
		if(StringUtils.isEmpty(permission.getPerid()) || StringUtils.isEmpty(permission.getPid())){
			return new SysError("参数错误.");
		}
		if(!"0".equals(permission.getPid())){
			SysPermission pPermission = get(permission.getPid());
			if(pPermission == null){
				return new SysError("参数错误.");
			}
		}
		if(isPeridDuplicate(permission.getPerid())){
			return new SysError("权限ID已存在，请使用其它ID.");
		}
		if(isPercodeDuplicate(permission.getPer_code(), null)){
			return new SysError("权限编号已存在，请使用其它编号.");
		}
		permission.setType("");
		permission.setIcon("");
		
		this.save(permission);
		return null;
	}
	
	
	/**
	 * 修改权限项
	 * 
	 * @param permission
	 * @return
	 */
	@CacheEvict(value="userRightsCache", allEntries = true)
	public Object update(SysPermission permission){
		evictCache("userRightsCache", null);
		if(StringUtils.isEmpty(permission.getPerid())){
			return new SysError("参数错误.");
		}
		SysPermission old = getSafeEntity(permission.getPerid());
		if(old == null){
			return new SysError("信息不存在.");
		}
		if(isPercodeDuplicate(permission.getPer_code(), permission.getPerid())){
			return new SysError("权限编号已存在，请使用其它编号.");
		}
		
		String fields = "per_code,per_name,remark,url,per_index";
		BeanUtil.setTargetFields(old, permission, fields, true);
		Updater<SysPermission> updater = new Updater<>(old, fields);
		this.update(updater);
		
		return null;
	}
	
	
	/**
	 * 删除指定的权限项
	 * 
	 * @param perids
	 * @return
	 */
	@CacheEvict(value="userRightsCache", allEntries = true)
	public Object delete(String[] perids){
		evictCache("userRightsCache", null);
		if(perids==null || perids.length==0){
			return new SysError("参数错误.");
		}
		for(String perid : perids){
			SysPermission permission = get(perid);
			if(permission == null){
				continue;
			}
			SysPermission childPermission = getByProperty("pid", perid);
			if(childPermission != null){
				return new SysError("权限项【"+permission.getPer_name()+"】包含有子权限项，不能直接删除，请先删除其子权限项.");
			}
			this.delete(permission);
		}
		return null;
	}
	
	
	
	/**
	 * 判断指定perid是否被使用
	 * 
	 * @param perid
	 * @return
	 */
	public boolean isPeridDuplicate(String perid){
		return isExists("perid", perid);
	}
	
	
	/**
	 * 判断指定per_code是否被使用
	 * @param per_code
	 * @param perid
	 * @return
	 */
	public boolean isPercodeDuplicate(String per_code, String perid){
		return isExists("per_code", per_code, "perid", perid);
	}
	
	
	
	/**
	 * 获取新的权限项ID
	 * 
	 * @param pid
	 * @return
	 */
	public String getNewID(String pid){
		String newid = (String) getByHql("select max(p.perid) from SysPermission p where p.pid=?", pid);
		if(newid==null){
			if(pid.equals("0")){
				return "P00";
			}else{
				return pid+"01";
			}
		}
		try {
			int n = Integer.parseInt(newid.substring(newid.length()-2, newid.length()));
			newid = pid + String.format("%02d", n+1);
			return newid;
		} catch (Exception e) {
		}
		return pid;
	}
	
	
	/**
	 * 获取新的权限项序号
	 * 
	 * @param pid
	 * @return
	 */
	public Integer getNewPerindex(String pid){
		Number maxIndex = (Number) getByHql("select max(p.per_index) from SysPermission p where p.pid=?", pid);
		int per_index = 0;
		if(maxIndex != null){
			per_index = maxIndex.intValue();
		}
		return per_index + 1;
	}
	
	
	/**
	 * 获取指定角色拥有的操作权限ID集合
	 * @param roleid
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Set<String> getRolePerids(String roleid){
		Set<String> set = new HashSet<String>();
		List<String> list = listByHql("select distinct r.sysPermission.perid from SysRoleRights r where r.sysRole.roleid=?", roleid);
		if(list != null){
			set.addAll(list);
		}
		return set;
	}
	
	
	/**
	 * 获取角色权限树
	 * @param roleid
	 * @param loginUser
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<SysPermission> getRoleRightsPermissions(String roleid, LoginUser loginUser){
		List<SysPermission> list = null;
		
		if(SystemCfg.isAdminUser(loginUser) || SystemCfg.isSystemAdminUser(loginUser)){
			list = listByHql("select new com.qingxin.sys.entity.SysPermission(perid, pid, per_name)" +
					" from SysPermission where per_index>0 order by per_index asc");
			
		}else {
			list = listByHql("select new com.qingxin.sys.entity.SysPermission(perid, pid, per_name)" +
					" from SysUserRightsView where per_index>0 and userid=? order by per_index asc", loginUser.getUserid());
			
		}
		if(list == null || list.size()==0){
			return new ArrayList<>();
		}
		Set<String> roleRights = getRolePerids(roleid);
		for(SysPermission perm : list){
			perm.setHasRights(roleRights.contains(perm.getPerid()));
		}
		return list;
	}
	
	
	
}
